package cn.com.acca.ma.dao.impl;

import cn.com.acca.ma.common.util.DateUtil;
import cn.com.acca.ma.dao.EtfTransactionDataDao;
import cn.com.acca.ma.enumeration.ExchangeBoardInfo;
import cn.com.acca.ma.jpa.util.JpaUtil;
import cn.com.acca.ma.model.EtfTransactionData;
import cn.com.acca.ma.model.StockTransactionData;
import cn.com.acca.ma.mybatis.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EtfTransactionDataDaoImpl extends BaseDaoImpl<EtfTransactionDataDaoImpl> implements EtfTransactionDataDao {

    public EtfTransactionDataDaoImpl() {
        super();
    }

    /**
     * 查找所有ETF某一日的前收盘
     *
     * @param date
     * @return
     */
    public List findLastClosePrice(Date date) {
        logger.info("查找所有ETF某一日【" + DateUtil.dateToString(date) + "】的前收盘");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String queryString = "select t1.code_ code, "
                + "       (select * from ("
                + "         	select t.close_price from etf_transaction_data t "
                + "         	where t.date_<? and t.code_=t1.code_ order by t.date_ desc "
                + "       		) t3 "
                + "		   where rownum<=1) lastClosePrice "
                + " from etf_transaction_data t1 "
                + "group by t1.code_";
        Query query = em.createNativeQuery(queryString);
        query.setParameter(1, date);
        List list = query.getResultList();

        em.getTransaction().commit();
        em.close();
        return list;
    }

    /**
     * 将从网络中（或.json文件中）读取的数据写入到表ETF_TRANSACTION_DATA中。
     *
     * @param etfTransactionDataList
     */
    public synchronized void writeEtfTransactionDataList(List<EtfTransactionData> etfTransactionDataList) {
        logger.debug("开始向表etf_transaction_data中插入数据");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        for (int i = 0; null != etfTransactionDataList
                && i < etfTransactionDataList.size(); i++) {
            EtfTransactionData etfTransactionData = etfTransactionDataList.get(i);

            em.persist(etfTransactionData);

////			Query query = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_STOCK_TRANSACTION_DATA(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");
//			Query query = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_STOCK_TRANSACTION_DATA(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");
//			query.setParameter(1, stockTransactionData.getDate());
////			query.setParameter(1, stockTransactionData.getCode());
//			query.setParameter(2, stockTransactionData.getOpenPrice());
//			query.setParameter(3, stockTransactionData.getClosePrice());
//			query.setParameter(4, stockTransactionData.getHighestPrice());
//			query.setParameter(5, stockTransactionData.getLowestPrice());
//			query.setParameter(6, stockTransactionData.getChangeAmount());
//			query.setParameter(7, stockTransactionData.getChangeRange());
//			query.setParameter(8, stockTransactionData.getTurnoverRate());
//			query.setParameter(9, stockTransactionData.getVolume());
//			query.setParameter(10, stockTransactionData.getTurnover());
//			query.setParameter(11, stockTransactionData.getTotalMarketValue());
//			query.setParameter(12, stockTransactionData.getCirculationMarketValue());
//			query.executeUpdate();
        }
        em.getTransaction().commit();
        em.close();
    }

    /*********************************************************************************************************************
     *
     * 									                             更新每天的数据
     *
     *********************************************************************************************************************/
    /**
     * 根据开始时间和结束时间，更新etf_transaction_data表的last_close_price、change_amount和change_range字段
     * @param beginDate
     * @param endDate
     */
    @Override
    public void writeEtfTransactionDataLastClosePriceByDate(String beginDate, String endDate) {
        logger.info("开始根据开始时间[" + beginDate + "]和结束时间[" + endDate + "]，更新etf_transaction_data表的last_close_price、change_amount和change_range字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_LAST_CLOSE_PRICE_BY_DATE(?,?)}");
        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("根据开始时间[" + beginDate + "]和结束时间[" + endDate + "]，更新etf_transaction_data表的last_close_price、change_amount和change_range字段完成");
    }

    /**
     * 根据日期date，计算某一日所有ETF的移动平均线数据
     *
     * @param date
     */
    @Override
    public void writeEtfTransactionDataMAByDate(String date) {
        logger.info("开始根据日期【" + date + "】，计算某一日所有ETF的移动平均线数据");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_ETF_T_D_MA_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("根据日期【" + date + "】，计算某一日所有ETF的移动平均线数据完成");
    }

    /**
     * 根据日期date，计算某一日所有ETF的Hei Kin Ashi数据
     *
     * @param date
     */
    @Override
    public void writeEtfTransactionDataHeiKinAshiByDate(String date) {
        logger.info("开始根据日期【" + date + "】，计算某一日所有ETF的Hei Kin Ashi数据");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_ETF_T_D_HA_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("根据日期【" + date + "】，计算某一日所有ETF的Hei Kin Ashi数据");
    }

    /**
     * 根据日期date，计算所有ETF某一日的乖离率
     *
     * @param date
     */
    @Override
    public void writeEtfTransactionDataBiasByDate(String date) {
        logger.info("开始根据日期【" + date + "】，计算所有ETF某一日的乖离率");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_ETF_T_D_BIAS_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("根据日期【" + date + "】，计算所有ETF某一日的乖离率");
    }

    /**
     * 更新表ETF_TRANSACTION_DATA中某一日的EMA15，EMA26，DIF和DEA字段
     *
     * @param date
     */
    @Override
    public void writeEtfTransactionDataMACDByDate(String date) {
        logger.info("开始更新表ETF_TRANSACTION_DATA中某一日【" + date + "】的EMA15，EMA26，DIF和DEA字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        Query query = em.createNativeQuery("{call pkg_etf.WRITE_MACD_EMA_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_MACD_DIF_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_MACD_DEA_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_MACD_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();

        em.getTransaction().commit();
        em.close();

        logger.info("更新表ETF_TRANSACTION_DATA中某一日【" + date + "】的EMA15，EMA26，DIF和DEA字段完成");
    }

    /**
     * 更新表ETF_TRANSACTION_DATA中某一日的RSV，K和D字段
     *
     * @param date
     */
    @Override
    public void writeEtfTransactionDataKDByDate(String date) {
        logger.info("开始更新表ETF_TRANSACTION_DATA中某一日【" + date + "】的RSV，K和D字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        Query query = em.createNativeQuery("{call pkg_etf.WRITE_KD_BY_DATE_RSV(?)}");
        query.setParameter(1, date);
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_KD_BY_DATE_K(?)}");
        query.setParameter(1, date);
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_KD_BY_DATE_D(?)}");
        query.setParameter(1, date);
        query.executeUpdate();

        em.getTransaction().commit();
        em.close();

        logger.info("更新表ETF_TRANSACTION_DATA中某一日【" + date + "】的RSV，K和D字段完成");
    }

    /**
     * 更新表ETF_TRANSACTION_DATA中某段时间的correlation***_with_avg_c_p字段
     * @param beginDate
     * @param endDate
     */
    @Override
    public void writeEtfTransactionDataCorrelationByDate(String beginDate, String endDate) {
        logger.info("开始更新表ETF_TRANSACTION_DATA中某段时间【" + beginDate + "】至【" + endDate + "】的correlation***_with_avg_c_p字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_CORRELATION250_BY_DATE(?, ?)}");
        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("更新表ETF_TRANSACTION_DATA中某段时间【" + beginDate + "】至【" + endDate + "】的correlation***_with_avg_c_p字段完成");
    }

    /*********************************************** 更新全部的数据 *****************************************************/
    /**
     * 海量更新etf_transaction_data表的last_close_price、change_amount和change_range字段
     */
    @Override
    public void writeEtfTransactionDataLastClosePrice() {
        logger.info("开始海量更新etf_transaction_data表的last_close_price、change_amount和change_range字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_LAST_CLOSE_PRICE}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("海量更新etf_transaction_data表的last_close_price、change_amount和change_range字段完成");
    }

    /**
     * 计算5日均线
     */
    @Override
    public void writeEtfTransactionDataMA5() {
        logger.info("开始计算所有etf的5日均线");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_FIVE}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("所有etf的5日均线计算完成");
    }

    /**
     * 计算10日均线
     */
    @Override
    public void writeEtfTransactionDataMA10() {
        logger.info("开始计算所有etf的10日均线");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_TEN}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("所有etf的10日均线计算完成");
    }

    /**
     * 计算20日均线
     */
    @Override
    public void writeEtfTransactionDataMA20() {
        logger.info("开始计算所有etf的20日均线");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_TWENTY}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("所有etf的20日均线计算完成");
    }

    /**
     * 计算60日均线
     */
    @Override
    public void writeEtfTransactionDataMA60() {
        logger.info("开始计算所有etf的60日均线");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_SIXTY}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("所有etf的60日均线计算完成");
    }

    /**
     * 计算120日均线
     */
    @Override
    public void writeEtfTransactionDataMA120() {
        logger.info("开始计算所有etf的120日均线");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_ONEHUNDREDTWENTY}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("所有etf的120日均线计算完成");
    }

    /**
     * 计算250日均线
     */
    @Override
    public void writeEtfTransactionDataMA250() {
        logger.info("开始计算所有etf的250日均线");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_TWOHUNDREDFIFTY}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("所有etf的250日均线计算完成");
    }

    /**
     * 计算所有ETF的乖离率
     */
    public void writeEtfTransactionDataBias() {
        logger.info("开始计算所有ETF的乖离率");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_ETF_TRANSACT_DATA_BIAS}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("计算所有ETF的乖离率完成");
    }

    /**
     * 计算Hei Kin Ashi相关的字段
     */
    public void writeEtfTransactionDataHeiKinAshi() {
        logger.info("开始计算Hei Kin Ashi的所有相关字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_etf.WRITE_ETF_TRANSACTION_DATA_HA}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("计算Hei Kin Ashi的所有相关字段完成");
    }

    /**
     * 计算所有ETF的MACD
     */
    @Override
    public void writeEtfTransactionDataMACD() {
        logger.info("开始计算所有ETF的MACD");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        Query query = em.createNativeQuery("{call pkg_etf.WRITE_MACD_INIT}");
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_MACD_EMA}");
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_MACD_DIF}");
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_MACD_DEA}");
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_MACD}");
        query.executeUpdate();

        em.getTransaction().commit();
        em.close();

        logger.info("计算所有ETF的MACD完成");
    }

    /**
     * 计算所有ETF的KD
     */
    @Override
    public void writeEtfTransactionDataKD() {
        logger.info("开始计算所有指数的KD");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        Query query = em.createNativeQuery("{call pkg_etf.WRITE_KD_INIT}");
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_KD_RSV}");
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_KD_K}");
        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_KD_D}");
        query.executeUpdate();

        em.getTransaction().commit();
        em.close();

        logger.info("计算所有ETF的KD完成");
    }

    /**
     * 计算所有ETF的correlation5_with***字段
     */
    @Override
    public void writeEtfTransactionDataCorrelation() {
        logger.info("开始计算所有ETF的correlation5_with***字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        Query query;

//        query = em.createNativeQuery("{call pkg_etf.WRITE_CORRELATION5}");
//        query.executeUpdate();

        query = em.createNativeQuery("{call pkg_etf.WRITE_CORRELATION250}");
        query.executeUpdate();

        em.getTransaction().commit();
        em.close();

        logger.info("计算所有ETF的correlation5_with***字段完成");
    }

    /*********************************************************************************************************************
     *
     * 									                 Robot6Main类过滤股票
     *
     *********************************************************************************************************************/
    /**
     * 根据开始日期和结束日期，查找中间的日期，并去重
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    @Override
    public List<String> findDistinctDateBetweenBeginDateAndEndDate(String beginDate, String endDate) {
        logger.info("开始根据开始日期【" + beginDate + "】和结束日期【" + endDate + "】，查找中间的日期，并去重");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        String sql = "select distinct b.date_ from ( "
                + "select to_char(t.date_, 'yyyy-mm-dd') date_ from etf_transaction_data t "
                + "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') order by t.date_ asc) b "
                + "order by b.date_ asc";
        Query query = em.createNativeQuery(sql);
        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        List<String> list = query.getResultList();
        em.getTransaction().commit();
        em.close();

        logger.info("根据开始日期【" + beginDate + "】和结束日期【" + endDate + "】，查找中间的日期，并去重完成");
        return list;
    }

    /**
     * 查找日期date的etf的代码，并且其最小日期小于minDate
     *
     * @param minDate
     * @param date
     * @return
     */
    @Override
    public List<String> findDistinctDateByDateAndLessThanMinDate(String minDate, String date) {
        logger.info("开始查找日期date【" + date + "】的etf的代码，并且其最小日期小于minDate【" + minDate + "】");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        String sql = "select distinct(t.code_) from etf_transaction_data t where t.date_=to_date(?,'yyyy-mm-dd') " +
                "and ( " +
                "select min(t1.date_) from etf_transaction_data t1 where t1.code_=t.code_ " +
                ")<=to_date(?,'yyyy-mm-dd')";
        Query query = em.createNativeQuery(sql);
        query.setParameter(1, date);
        query.setParameter(2, minDate);
        List<String> list = query.getResultList();
        em.getTransaction().commit();
        em.close();

        logger.info("开始查找日期date【" + date + "】的etf的代码，并且其最小日期小于minDate【" + minDate + "】完成");
        return list;
    }

    /**
     * 查找日期date之前的最近一个交易日的日期
     *
     * @param date
     * @return
     */
    @Override
    public String findLatestDate(String date) {
        logger.info("开始查找日期date【" + date + "】之前的最近一个交易日的日期");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        String sql = "select to_char(t1.date_, 'yyyy-mm-dd')  from ( " +
                "select * from etf_transaction_data t where t.date_<=to_date(?,'yyyy-mm-dd') order by t.date_ desc) t1 " +
                "where rownum<=1";
        Query query = em.createNativeQuery(sql);
        query.setParameter(1, date);
        List<String> list = query.getResultList();
        em.getTransaction().commit();
        em.close();

        logger.info("查找日期date【" + date + "】之前的最近一个交易日的日期完成");
        if (null != list && list.size() > 0) {
            return list.get(0);
        } else {
            return null;
        }
    }

    /**
     * 查找日期date之后的最近一个交易日的日期
     *
     * @param date
     * @return
     */
    @Override
    public String findNextDate(String date) {
        logger.info("开始查找日期date【" + date + "】之后的最近一个交易日的日期");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        String sql = "select to_char(t1.date_, 'yyyy-mm-dd')  from ( " +
                "select * from etf_transaction_data t where t.date_>=to_date(?,'yyyy-mm-dd') order by t.date_ asc) t1 " +
                "where rownum<=1";
        Query query = em.createNativeQuery(sql);
        query.setParameter(1, date);
        List<String> list = query.getResultList();
        em.getTransaction().commit();
        em.close();

        logger.info("查找日期date【" + date + "】之后的最近一个交易日的日期完成");
        if (null != list && list.size() > 0) {
            return list.get(0);
        } else {
            return null;
        }
    }

    /*********************************************************************************************************************
     *
     * 									                             根据每日数据更新图表
     *
     *********************************************************************************************************************/
    /**
     * 获取某一段时间内平均价格中的最大价格和最小价格
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @return
     */
    public List getMaxMinAverageCloseWeek(boolean multithreading, String beginDate, String endDate) {

        List list;
        String queryString = new String("select max(avg(t.close_price)),min(avg(t.close_price)) from etf_transaction_data t " +
                "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') " +
                "group by t.date_ order by t.date_ asc");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryString);
        }

        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        list = query.getResultList();

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return list;
    }

    /**
     * 获取从开始日期至结束日期，每个交易日所有ETF的平均价格（所有ETF的收盘价之和/参加交易的ETF的数量）
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @return
     */
    public List getAverageCloseWithDate(boolean multithreading, String beginDate, String endDate) {
        String queryClose = new String(
                "select * from (select t.date_,sum(t.close_price)/count(t.code_) from etf_transaction_data t " +
                        "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') group by t.date_) o " +
                        "order by o.date_ asc");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery(queryClose);
        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        List list = query.getResultList();
        em.getTransaction().commit();
        em.close();

        return list;
    }
}
